﻿using MongoDB.Driver;
using Sustainalytics.BusinessResearchProductStates.Entities.ResearchState;
using Sustainalytics.ClientDW.DataAccessLayer;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.DataLayer;
using Sustainalytics.DataLayer.PI;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.Entities.ProductInvolvement;
using Sustainalytics.MongoDB.Extensions;
using Sustainalytics.Synchronization.Interface;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using SimpleInjector;
using static Sustainalytics.Utils.AssessementList;

namespace Sustainalytics.ProductInvolvement.BL
{
    public class ProductInvolvementBussinesLogic : IProductInvolvementBussinesLogic
    {
        private IProductInvolvementDataRepository _companyRepository;
        private IClientDwRepository _dwRepository;
        private IProductInvolvementFrameworkRepository _piFrameworkRepository;
        private ICompanyScreeningRepository _companyScreeningRepository;

        private IRepositoryCollection<CorporateData> _repositoryCorporateData;
        private IRepositoryCollection<ProductInvolvementData> _repositoryPiCompanyAssesment;
        private IMongoCollection<CorporateData> _corporateDataCollection;

        protected Container SimpleInjectorContainer;

        public ProductInvolvementBussinesLogic()
        {
        }

        public ProductInvolvementBussinesLogic(
            IProductInvolvementDataRepository companyRepository,
            IClientDwRepository dwRepository,
            IProductInvolvementFrameworkRepository piFrameworkRepository,
            ICompanyScreeningRepository companyScreeningRepository,
            ProductInvolvementSerilog log,
            IMongoCollection<CorporateData> corporateDataCollection,
            IRepositoryCollection<CorporateData> repositoryCorporateData,
            IRepositoryCollection<ProductInvolvementData> repositoryPiCompanyAssesment)
        {
            _companyRepository = companyRepository;
            _piFrameworkRepository = piFrameworkRepository;
            _dwRepository = dwRepository;
            _companyScreeningRepository = companyScreeningRepository;
            _corporateDataCollection = corporateDataCollection;
            _repositoryCorporateData = repositoryCorporateData;
            _repositoryPiCompanyAssesment = repositoryPiCompanyAssesment;
        }

        public static ProductInvolvementBussinesLogic CreateProductInvolvementBussinesLogic(
            IFileRepository fileRepository,
            IProductInvolvementDataRepository companyRepository,
            IClientDwRepository dwRepository,
            IProductInvolvementFrameworkRepository piFrameworkRepository,
            ICompanyScreeningRepository companyScreeningRepository,
            ProductInvolvementSerilog log,
            IMongoCollection<CorporateData> corporateDataCollection,
            IRepositoryCollection<CorporateData> repositoryCorporateData,
            IRepositoryCollection<ProductInvolvementData> repositoryPiCompanyAssesment
            )
        {

            return new ProductInvolvementBussinesLogic
            {
                _companyRepository = companyRepository,
                _dwRepository = dwRepository,
                _piFrameworkRepository = piFrameworkRepository,
                _companyScreeningRepository = companyScreeningRepository,
                _corporateDataCollection = corporateDataCollection,
                _repositoryCorporateData = repositoryCorporateData,
                _repositoryPiCompanyAssesment = repositoryPiCompanyAssesment
        };
               
        }

        public virtual ProductInvolvementData ReadCompanyAssessment(List<int> userUniverseIds, List<string> claimedIndicators, Guid companyId)
        {
            var corpData = _dwRepository.GetCorporateDataByCompanyId(companyId);
            var productInvolvementResearchState = ResearchState.ResearchNotAvailable;

            if (corpData == null)
                return _companyRepository.ReadById(userUniverseIds, claimedIndicators, companyId, productInvolvementResearchState);

            if (corpData.UniverseIds == null || !corpData.UniverseIds.Where(x => userUniverseIds.Contains(x)).Any())
            {
                throw new PICompanyAssessmentNotInUniversesException();
            }

            productInvolvementResearchState = corpData.ProductInvolvementResearchState.ResearchState;

            return _companyRepository.ReadById(userUniverseIds, claimedIndicators, companyId, productInvolvementResearchState);
        }

        public virtual IEnumerable<ProductInvolvementFramework> ReadPIIndicators()
        {
            return _piFrameworkRepository.ReadIndicators();
        }

        public virtual CorporateData GetCorporateDataByCompanyId(Guid companyId)
        {
            return _dwRepository.GetCorporateDataByCompanyId(companyId);
        }

        //PI company assessment
        public virtual IEnumerable<ProductInvolvementData> ReadCompanyAssessment(int skip, int take, string sort, bool sortascending)
        {
            return _companyRepository.Read(skip, take, sort, sortascending);
        }

        //PI companies list
        public virtual IEnumerable<CompanyList> ReadCompanyAssessmentShortReport(
            ProductInvolvementDataListFilters filters,
            List<int> userUniverseIds,
            List<string> claimedIndicators,
            int skip,
            int take,
            string[] orderBy = null,
            bool orderByAsc = true)
        {
            return _companyRepository.Read(filters, userUniverseIds, claimedIndicators, skip, take, orderBy, orderByAsc);
        }

        public virtual long ReadCompanyAssessmentShortReportCount(ProductInvolvementDataListFilters filters, List<int> userUniverseIds, List<string> claimedIndicators)
        {
            return _companyRepository.ReadCount(filters, userUniverseIds, claimedIndicators);
        }

        public string Report()
        {
            return logBuilder.ToString();
        }

        private IEnumerable<ChangedElement> previousChanges;
        private SyncOperationStatus currentStatus;
        private StringBuilder logBuilder;


        public IList<ProductInvolvementCategory> GetIndicatorCategories(string piSymbol)
        {
            return _piFrameworkRepository.GetIndicatorCategories(piSymbol);
        }

        public Guid GetTemplateCriteriaIdByPISymbol(string piSymbol)
        {
            return _companyScreeningRepository.GetTemplateCriteriaIdByPISymbol(piSymbol);
        }
    }
}
